package com.xiaoyu.base.model;

import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.xiaoyu.base.DBCall;
import com.xiaoyu.base.dao.UserDao;
import com.xiaoyu.base.entity.UserEntity;
import com.xiaoyu.base.event.UserAvatarUpdateEvent;
import com.xiaoyu.base.event.UserDecorateIconUpdateEvent;
import com.xiaoyu.base.event.UserGuardIconUpdateEvent;
import com.xiaoyu.base.event.UserNameUpdateEvent;
import com.xiaoyu.base.data.UserData;


import java.io.Serializable;

import in.srain.cube.request.JsonData;
import in.srain.cube.util.CLog;
import kotlin.jvm.functions.Function2;

public class User implements Serializable {

    public static final User NOBODY = new User();

    public final static String SEX_UNKNOWN = "UNKNOWN";
    public final static String SEX_MAN = "MAN";
    public final static String SEX_WOMAN = "WOMAN";

    static {
        NOBODY.mUid = "";
        NOBODY.mName = "";
        NOBODY.mAvatar = "";
        NOBODY.mSex = SEX_UNKNOWN;
        NOBODY.mRemark = "";
        NOBODY.mDecorateKey = "";
        NOBODY.mGuardKey = "";
    }

    private String mUid;
    private String mName;
    private String mAvatar;
    private String mSex;
    private String mRemark;
    private String mDecorateKey;
    private String mGuardKey;

    private static Function2<String, String, String> sRemarkFunction;

    public static void setRemarkFunction(Function2<String, String, String> remarkFunction) {
        User.sRemarkFunction = remarkFunction;
    }

    protected User() {
    }

    protected User(String uid, JsonData jsonData) {
        mUid = uid;
        mAvatar = jsonData.optString("avatar");
        mDecorateKey = jsonData.optString("decorate_key");
        mGuardKey = jsonData.optString("guard_key");
        mSex = jsonData.optString("sex");
        mName = jsonData.optString("name");
        mRemark = mName;
        if (sRemarkFunction != null) {
            mRemark = sRemarkFunction.invoke(uid, mName);
        }
    }

    public static User fromJson(JsonData jsonData) {
        final String uid = jsonData.optString("id");
        if (!TextUtils.isEmpty(uid)) {
            return new User(uid, jsonData);
        }
        return NOBODY;
    }

    public static User loadFromDb(String uid) {
        if (TextUtils.isEmpty(uid)) {
            return NOBODY;
        }
        try {
            UserEntity entity = DBCall.call(database -> database.userDao().getUserByUid(uid));
            return User.fromUserEntity(entity);
        } catch (Throwable e) {
            CLog.e(UserDao.LOG_TAG, "user loadFromDb fail: %s", e);
            return NOBODY;
        }
    }

    public static User fromUserEntity(UserEntity entity) {
        if (entity == null) {
            return NOBODY;
        }
        User user = new User();
        final String uid = entity.getUid();
        user.mUid = uid;
        user.mAvatar = entity.getAvatar();
        user.mDecorateKey = entity.getDecorateKey();
        user.mGuardKey = entity.getGuardKey();
        user.mSex = entity.getSex();
        user.mName = entity.getName();
        user.mRemark = user.mName;
        if (sRemarkFunction != null) {
            user.mRemark = sRemarkFunction.invoke(uid, user.mName);
        }
        return user;
    }

    public UserEntity toEntity() {
        final UserEntity entity = new UserEntity();
        entity.setUid(mUid);
        entity.setSex(mSex);
        entity.setAvatar(mAvatar);
        entity.setDecorateKey(mDecorateKey);
        entity.setGuardKey(mGuardKey);
        entity.setName(mName);
        return entity;
    }

    @NonNull
    @Override
    public String toString() {
        return "User{" +
                "mUid='" + mUid + '\'' +
                ", mAvatar='" + mAvatar + '\'' +
                ", mDecorateKey='" + mDecorateKey + '\'' +
                ", mGuardKey='" + mGuardKey + '\'' +
                ", mSex=" + mSex +
                ", mRemark='" + mRemark + '\'' +
                ", mName='" + mName +
                '}';
    }

    public JsonData toJson() {
        JsonData jsonData = JsonData.newMap();
        jsonData.put("id", mUid);
        jsonData.put("name", mRemark);
        jsonData.put("sex", mSex);
        jsonData.put("avatar", mAvatar);
        jsonData.put("decorate_key", mDecorateKey);
        jsonData.put("guard_key", mGuardKey);
        return jsonData;
    }

    public String getUid() {
        return mUid;
    }

    public void setUid(String uid) {
        this.mUid = uid;
    }

    public String getSex() {
        return mSex;
    }

    public String getSexDesc() {
        return getSexDesc(mSex);
    }

    public static String getSexDesc(String sex) {
        switch (sex) {
            case SEX_MAN:
                return "男";
            case SEX_WOMAN:
                return "女";
        }
        return "";
    }

    public void setAvatar(String avatar) {
        mAvatar = avatar;
    }

    public String getAvatar() {
        return mAvatar;
    }

    public String getDecorateKey() {
        return mDecorateKey;
    }

    public String getGuardKey() {
        return mGuardKey;
    }

    public void setDecorateIcon(String decorateIcon) {
        mDecorateKey = decorateIcon;
    }

    public void setmGuardKey(String mGuardKey) {
        this.mGuardKey = mGuardKey;
    }

    public boolean hasDecorate() {
        return !TextUtils.isEmpty(mDecorateKey);
    }

    public boolean hasGuard() {
        return !TextUtils.isEmpty(mGuardKey);
    }

    public boolean isMale() {
        return mSex.equals(SEX_MAN);
    }

    public String getRemark() {
        return mRemark;
    }

    public void notifyNameUpdate() {
        mRemark = mName;
        if (sRemarkFunction != null) {
            mRemark = sRemarkFunction.invoke(mUid, mName);
        }
        new UserNameUpdateEvent(this).post();
    }

    public boolean tryToUpdateFrom(User newUser) {
        if (newUser == null) {
            return false;
        }
        if (!TextUtils.equals(newUser.getUid(), mUid)) {
            return false;
        }

        boolean isModified = false;

        if (!TextUtils.equals(newUser.mSex, mSex)) {
            mSex = newUser.mSex;
            isModified = true;
        }

        if (!TextUtils.equals(newUser.getName(), mName)) {
            mName = newUser.getName();
            notifyNameUpdate();
            isModified = true;
        }

        if (!TextUtils.equals(newUser.getAvatar(), mAvatar)) {
            mAvatar = newUser.getAvatar();
            new UserAvatarUpdateEvent(this).post();
            isModified = true;
        }
        if (!TextUtils.equals(newUser.getDecorateKey(), mDecorateKey)) {
            mDecorateKey = newUser.getDecorateKey();
            new UserDecorateIconUpdateEvent(this).postSticky();
            isModified = true;
        }
        if (!TextUtils.equals(newUser.getGuardKey(), mGuardKey)) {
            mGuardKey = newUser.getGuardKey();
            new UserGuardIconUpdateEvent(this).postSticky();
            isModified = true;
        }
        return isModified;
    }

    public String getName() {
        return mName;
    }

    public boolean isNobody() {
        return TextUtils.isEmpty(mUid);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (!User.class.isAssignableFrom(obj.getClass())) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        final User theOther = (User) obj;
        if (!TextUtils.equals(theOther.mUid, mUid)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        if (!TextUtils.isEmpty(mUid)) {
            hash = hash * 53 + mUid.hashCode();
        }
        return hash;
    }

    public boolean isSameContent(User user) {
        if (this == user) return true;
        if (user == null) return false;
        if (mSex != user.mSex) return false;
        if (!TextUtils.equals(mUid, user.mUid)) return false;
        if (!TextUtils.equals(mAvatar, user.mAvatar)) return false;
        if (!TextUtils.equals(mDecorateKey, user.mDecorateKey)) return false;
        if (!TextUtils.equals(mGuardKey, user.mGuardKey)) return false;
        if (!TextUtils.equals(mRemark, user.mRemark)) return false;
        return TextUtils.equals(mName, user.mName);
    }

    public boolean isSelf() {
        return UserData.getInstance().isSelf(mUid);
    }
}
